#pragma once
#include <list>

namespace gtl
{

namespace patterns
{

namespace detail
{

template<class GenePrime, class GeneSub>
class mix : public GenePrime, public GeneSub
{
public:
	virtual ~mix() { }
};

template<class Component>
class component : public Component
{
public:
	typedef component<Component> component_type;

public:
	component() : m_parent(NULL)
	{
	}

	virtual ~component()
	{
	}

public:
	virtual component_type* get_composite() = 0;
	virtual void add(Component* child) = 0;
	virtual void remove(Component* child) = 0;
	virtual void erase(Component* child) = 0;

	virtual void parent(Component* prnt)
	{
		m_parent = static_cast<component_type*>(prnt);
	}

	virtual component_type* parent()
	{ 
		return m_parent;
	}

protected:
	component_type* m_parent;
};

} // end of namespace

template<class Component>
class leaf : public detail::component<Component>
{
public:
	typedef leaf<Component> leaf_type;

public:
	virtual ~leaf()
	{
	}

public:
	virtual component_type* get_composite()
	{ 
		return NULL;
	}

private:
	virtual void add(Component*)	{ }
	virtual void remove(Component*) { }
	virtual void erase(Component*)	{ }
};

template<class Component>
class composite : public detail::component<Component>
{
public:
	typedef composite<Component> composite_type;
	typedef std::list<Component*> children_type;

public:
	virtual ~composite()
	{
		clear();
	}

public:
	virtual void add(Component* child)
	{
		if(child == NULL)
			return;

		m_children.push_back(child);
		static_cast<component_type*>(child)->parent(this);
	}

	virtual void insert(Component* child, size_t index)
	{
		if(child == NULL)
			return;

		if(index >= m_children.size())
		{
			m_children.push_back(child);
		}
		else
		{
			int i = 0;
			for(children_type::iterator ite = m_children.begin(); ite != m_children.end(); ++ite, ++i)
			{
				if(i == index)
				{
					m_children.insert(ite, child);
					break;
				}
			}
		}

		static_cast<component_type*>(child)->parent(this);
	}

	virtual void remove(Component* child)
	{
		m_children.remove(child);
	}

	virtual void erase(Component* child)
	{
		m_children.remove(child);
		delete child;
	}

	virtual children_type& children(void)
	{
		return m_children;
	}

	virtual const children_type& children(void) const
	{
		return m_children;
	}

	virtual component_type* get_composite(void)
	{
		return this;
	}

	virtual void clear()
	{
		children_type::iterator first = m_children.begin();
		children_type::iterator last = m_children.end();
		for(; first != last; ++first)
		{
			delete *first;
		}

		m_children.clear();
	}

protected:
	children_type m_children;
};

} // end namespace patterns

} // end namespace gtl